﻿using Myotragus.Data.Domain;
using Myotragus.Data.Metadata;
using NHibernate.Criterion;

namespace Myotragus.Data.Criteria
{
	public class LocalizableEntityProjector<TEntity> : EntityProjector<TEntity>,
														 ILocalizableEntityProjector<TEntity>
		where TEntity : IEntity
	{
		public LocalizableEntityProjector(ILocalizableEntityDescriptor<TEntity> descriptor,
			ILocalizableEntityMapping mapping)
			: base()
		{
			Descriptor = descriptor;
			Mapping = mapping;
		}

		protected ILocalizableEntityMapping Mapping { get; private set; }

		protected ILocalizableEntityDescriptor<TEntity> Descriptor { get; private set; }

		public override IProjection GetProjection(string path)
		{
			var list = Projections.ProjectionList();

			AddLocalizableProperties(list, Descriptor, path);
			AddNonLocalizableProperties(list, Descriptor, path);

			return list;
		}

		protected void AddNonLocalizableProperties(ProjectionList list, 
			ILocalizableEntityDescriptor<TEntity> descriptor, string path)
		{
			foreach (var property in Mapping.GetLocalizableProperties(typeof(TEntity)))
			{
				list.Add(CreateNonLocalizablePropertyProjection(property.PropertyName, path), 
					property.PropertyName);
			}
		}

		protected virtual IProjection CreateNonLocalizablePropertyProjection(string property, string path)
		{
			return Projections.GroupProperty(
				string.Format(string.IsNullOrEmpty(path) ? "{0}" : "{1}.{0}", property, path));
		}

		protected void AddLocalizableProperties(ProjectionList list, ILocalizableEntityDescriptor<TEntity> descriptor, string path)
		{
			foreach (var p in Mapping.GetLocalizableProperties(typeof(TEntity)))
				list.Add(CreateLocalizablePropertyProjection(p.PropertyName, path));
		}

		protected virtual IProjection CreateLocalizablePropertyProjection(string property, string path)
		{
			return Projections.GroupProperty(
				string.Format(string.IsNullOrEmpty(path) ?
				"{0}.Value" : "{1}.Value", property, path));
		}
	}
}